// url转base64
function canvasDataURL (path, quality, callback) {
    var that = this;
    var img = new Image();
    img.src = path; ///base64格式数据
    img.onload = function () {
        var w = this.width * quality,
            h = this.height * quality;
        //生成canvas
        var canvas = document.createElement("canvas");
        var ctx = canvas.getContext("2d");
        // 创建属性节点
        var anw = document.createAttribute("width");
        anw.nodeValue = w;
        var anh = document.createAttribute("height");
        anh.nodeValue = h;
        canvas.setAttributeNode(anw);
        canvas.setAttributeNode(anh);
        ctx.drawImage(img, 0, 0, w, h);
        var base64 = canvas.toDataURL("image/jpeg", 1);
        // 回调函数返回base64的值
        callback(base64);
    };
}
// base64转blob
function convertBase64UrlToBlob (urlData) {
    var arr = urlData.split(","),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n);
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new Blob([u8arr], { type: mime });
}
//将blob转换成file
function blobToFile (theBlob, fileName) {
    theBlob.lastModifiedDate = new Date();
    theBlob.name = fileName;
    return theBlob;
}
// var file = blobToFile(dataURLtoBlob(dataurl), fileName)
// 以上IE上传:
// 以上非IE上传:
//将base64直接转换为文件，低版本的浏览器不支持，不支持Uint8Array（），File（）
// Uint8Array（）,blob,有polyfill,IE10 及以上input 有files 属性，ie9 下没有这个属性
function dataURLtoFile (dataurl, filename) {
    var arr = dataurl.split(","),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n);
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new File([u8arr], filename, { type: mime });
}
/* 判断浏览器版本是否支持Blob */
var array = new Int8Array([17, -45.3]);
try {
    var jpeg = new Blob([array], { type: "image/jpeg" });
} catch (e) {
    // TypeError old chrome and FF
    window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
    if (e.name == 'TypeError' && window.BlobBuilder) {
        var bb = new BlobBuilder();
        bb.append(array.buffer);
        var jpeg = bb.getBlob("image/jpeg");
    } else if (e.name == "InvalidStateError") {
        // InvalidStateError (tested on FF13 WinXP)
        var jpeg = new Blob([array.buffer], { type: "image/jpeg" });
    } else {
        // We're screwed, blob constructor unsupported entirely
    }
}
/* /判断浏览器版本是否支持Blob */
// 兼容blob代码
var NewBlob = function (data, datatype) {
    var out;
    try {
        out = new Blob([data], { type: datatype });
        console.debug("case 1");
    } catch (e) {
        window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
        if (e.name == 'TypeError' && window.BlobBuilder) {
            var bb = new BlobBuilder();
            bb.append(data);
            out = bb.getBlob(datatype);
            console.debug("case 2");
        } else if (e.name == "InvalidStateError") {
            // InvalidStateError (tested on FF13 WinXP)
            out = new Blob([data], { type: datatype });
            console.debug("case 3");
        } else {
            // We're screwed, blob constructor unsupported entirely
            console.debug("Errore");
        }
    }
    return out;
}
/* 判断浏览器版本是否支持File */
function isSupportFileApi () {
    if (window.File && window.FileList && window.FileReader && window.Blob) { return true; }
    return false;
}
/* /判断浏览器版本是否支持File */
// reader.readAsBinaryString(file);readAsArrayBuffer方法读取文件，返回一个类型化数组（ArrayBuffer），即固定长度的二进制缓存数据。
// 与XMLHttpRequest.sendAsBinary方法结合使用，就可以使用JavaScript上传任意文件到服务器。
// 解决IE不支持html5 file api中readAsBinaryString,重写readAsBinaryString，用IE支持的方式
FileReader.prototype.readAsBinaryString = function (fileData) {
    var binary = "";
    var pt = this;
    var reader = new FileReader();
    reader.onload = function (e) {
        var bytes = new Uint8Array(reader.result);
        var length = bytes.byteLength;
        for (var i = 0; i < length; i++) {
            binary += String.fromCharCode(bytes[i]);
        }
        //pt.result  - readonly so assign binary
        pt.content = binary;
        $(pt).trigger('onload');
    }
}
// readAsBinaryString(Blob|File)：返回二进制字符串，该字符串每个字节包含一个0到255之间的整数。
// readAsText(Blob|File, opt_encoding) ：返回文本字符串。默认情况下，文本编码格式是'UTF-8'，可以通过可选的格式参数，指定其他编码格式的文本。
// readAsDataURL(Blob|File)：返回一个基于Base64编码的data-uri对象。
// readAsArrayBuffer(Blob|File) ：返回一个ArrayBuffer对象。
// onabort方法：读取中断或调用reader.abort()方法时触发。
// onerror方法：读取出错时触发。
// onload方法：读取成功后触发。
// onloadend方法：读取完成后触发，不管是否成功。触发顺序排在 onload 或 onerror 后面。
// onloadstart方法：读取将要开始时触发。
// onprogress方法：读取过程中周期性触发。
// BinaryString通过btoa转换base64
// base-64 解码使用方法是 atob()
var reader = new FileReader();
reader.readAsBinaryString(fileData);
reader.onload = function (e) {
    if (reader.result) reader.content = reader.result;
    var base64Data = btoa(reader.content);
    //...
}
//extend FileReader
if (!FileReader.prototype.readAsBinaryString) {
    FileReader.prototype.readAsBinaryString = function (fileData) {
        var binary = "";
        var pt = this;
        var reader = new FileReader();
        reader.onload = function (e) {
            var bytes = new Uint8Array(reader.result);
            var length = bytes.byteLength;
            for (var i = 0; i < length; i++) {
                binary += String.fromCharCode(bytes[i]);
            }
            //pt.result  - readonly so assign binary
            pt.content = binary;
            $(pt).trigger('onload');
        }
        reader.readAsArrayBuffer(fileData);
    }
}
// 转换Unicode兼容
// ucs-2 string to base64 encoded ascii
function utoa (str) {
    return window.btoa(unescape(encodeURIComponent(str)));
}
// base64 encoded ascii to ucs-2 string
function atou (str) {
    return decodeURIComponent(escape(window.atob(str)));
}
// let encodedData = window.btoa("Hello, world"); // base64 编码
// let decodedData = window.atob(encodedData); // 解码 成 ASCII
// // Usage:
// utoa('✓ à la mode'); // 4pyTIMOgIGxhIG1vZGU=
// atou('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"
// utoa('I \u2661 Unicode!'); // SSDimaEgVW5pY29kZSE=
// atou('SSDimaEgVW5pY29kZSE='); // "I ♡ Unicode!"




//阻止事件冒泡的兼容写法
function stopBubble (e) {
    //如果提供了事件对象，则是一个非IE浏览器
    if (e && e.stopPropagation)
        //因此它支持W3C的stopPropagation()方法
        e.stopPropagation();
    else
        //否则，我们需要使用IE的方式来取消事件冒泡
        window.event.cancelBubble = true;
}
/**
 * 兼容ie8的indexOf方法
 */
function compatibleIndexOf () {
    if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function (elt /*, from*/) {
            var len = this.length >>> 0;
            var from = Number(arguments[1]) || 0;
            from = (from < 0) ? Math.ceil(from) : Math.floor(from);
            if (from < 0) from += len;
            for (; from < len; from++) {
                if (from in this && this[from] === elt) return from;
            }
            return -1;
        };
    }
}
// 生成UUID
function getUuid () {
    var len = 32; //32长度
    var radix = 16; //16进制
    var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
    var uuid = [],
        i;
    radix = radix || chars.length;
    if (len) {
        for (i = 0; i < len; i++) {
            uuid[i] = chars[0 | Math.random() * radix];
        }
        var r;
        uuid[8] = uuid[13] = uuid[18] = uuid[23] = '';
        uuid[14] = '4';
        for (i = 0; i < 36; i++) {
            if (!uuid[i]) {
                r = 0 | Math.random() * 16;
                uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
            }
        }
    }
    return uuid.join('').toLowerCase();;
}

/*=========== 标准时间字符串转时间戳  =======================*/
function standardTimeToStamp (standardTime) {
    var isStandardTime = /^(\d{4})\-(\d{2})\-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/.test(standardTime);

    if (isStandardTime) {
        return Date.parse(standardTime.replace(/-/g, "/"));
    } else {
        return Date.parse(new Date());
    }
}


// 根据时间戳生成标准时间
function format (shijian) {
    let date = new Date(shijian)
    var y = date.getFullYear();
    var m = date.getMonth() + 1;
    m = m < 10 ? ('0' + m) : m;
    var d = date.getDate();
    d = d < 10 ? ('0' + d) : d;
    var h = date.getHours();
    h = h < 10 ? ('0' + h) : h;
    var minute = date.getMinutes();
    minute = minute < 10 ? ('0' + minute) : minute;
    var second = date.getSeconds();
    second = second < 10 ? ('0' + second) : second;
    return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second;
};
// 时间戳转时间
function timestampToTime (timestamp) {
    var date = new Date(timestamp);
    Y = date.getFullYear() + '-';
    M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
    D = (date.getDate() < 10) ? '0' + date.getDate() : date.getDate() + '';
    return Y + M + D;
}
//日期格式转换
function sts_date_L (s) { // 年-月-日
    var date = new Date(s);
    var year = date.getFullYear();
    var month = date.getMonth() + 1; //js从0开始取
    var date1 = date.getDate();
    if (month >= 1 && month <= 9) {
        month = "0" + month;
    };
    if (date1 >= 0 && date1 <= 9) {
        date1 = "0" + date1;
    };
    var h = (year + "年" + month + "月" + date1 + "日");
    return h;
};
// 获取当前时间
function getNowDate () {
    let date = new Date();
    let seperator1 = '-';
    let seperator2 = ':';
    let month = date.getMonth() + 1;
    let hour = date.getHours();
    let minute = date.getMinutes();
    let second = date.getSeconds();
    let strDate = date.getDate();
    if (month >= 1 && month <= 9) {
        month = '0' + month;
    }
    if (strDate >= 0 && strDate <= 9) {
        strDate = '0' + strDate;
    }
    if (hour >= 0 && hour <= 9) {
        hour = '0' + hour;
    }
    if (second >= 0 && second <= 9) {
        second = '0' + second;
    }
    if (minute >= 0 && minute <= 9) {
        minute = '0' + minute;
    }
    let currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate + ' ' + hour + seperator2 + minute + seperator2 + second;
    return currentdate;
}
// 数组对象去重
function distinct (arr, key) {
    var newobj = {},
        newArr = [];
    for (var i = 0; i < arr.length; i++) {
        var item = arr[i];
        if (!newobj[item[key]]) {
            newobj[item[key]] = newArr.push(item);
        }
    }
    return newArr;
}
/*判断空值*/
function isNull (item) {
    var ret = false;
    if (!item || item == '' || typeof (item) == 'undefined') {
        ret = true;
    }
    return ret;
}
//数字每3位加“,” 如：1,2222
function renderNum (num) {
    var ret = "";
    ret += num;
    if (num != null && num != '') {
        ret = ret.split("").reverse().join("").replace(/(\d{3})(?=[^$])/g, "$1,").split("").reverse().join("");
    }
    return ret;
}
function Append_zore (temp) {
    if (temp < 10) {
        return "0" + temp;
    } else {
        return temp;
    }
}

/* 通过出生日期计算年龄
 * 参数 strBirthday :出生日期
 * return 周岁年龄
 */
function jsGetAge (strBirthday) {
    var da = new Date(strBirthday);
    var returnAge;
    //var strBirthdayArr=strBirthday.split("-");
    var birthYear = da.getYear();
    var birthMonth = da.getMonth() + 1;
    var birthDay = da.getDate();
    var d = new Date();
    var nowYear = d.getYear();
    var nowMonth = d.getMonth() + 1;
    var nowDay = d.getDate();
    if (nowYear == birthYear) {
        returnAge = 0; //同年 则为0岁
    } else {
        var ageDiff = nowYear - birthYear; //年之差
        if (ageDiff > 0) {
            if (nowMonth == birthMonth) {
                var dayDiff = nowDay - birthDay; //日之差
                if (dayDiff < 0) {
                    returnAge = ageDiff - 1;
                } else {
                    returnAge = ageDiff;
                }
            } else {
                var monthDiff = nowMonth - birthMonth; //月之差
                if (monthDiff < 0) {
                    returnAge = ageDiff - 1;
                } else {
                    returnAge = ageDiff;
                }
            }
        } else {
            returnAge = -1; //返回-1 表示出生日期输入错误 晚于今天
        }
    }
    return returnAge; //返回周岁年龄
}
// 通过身份证获取出生日期1995-04-20
// iIdNo:string
// return 1995-04-20
function getBirthdatByIdNo (iIdNo) {
    var tmpStr = "";
    var strReturn = "";
    if (iIdNo.length == 15) {
        tmpStr = iIdNo.substring(6, 12);
        tmpStr = "19" + tmpStr;
        tmpStr = tmpStr.substring(0, 4) + "-" + tmpStr.substring(4, 6) + "-" + tmpStr.substring(6)
        return tmpStr;
    } else {
        tmpStr = iIdNo.substring(6, 14);
        tmpStr = tmpStr.substring(0, 4) + "-" + tmpStr.substring(4, 6) + "-" + tmpStr.substring(6)
        return tmpStr;
    }
}
// 根据2019-10-20获取年龄
function getAge (str) {
    var r = str.match(/^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/);
    if (r == null) return false;
    var d = new Date(r[1], r[3] - 1, r[4]);
    if (d.getFullYear() == r[1] && (d.getMonth() + 1) == r[3] && d.getDate() == r[4]) {
        var Y = new Date().getFullYear();
        return (Y - r[1]) > 0 && (Y - r[1]) ? (Y - r[1]) : "";
    }
}
// 通过身份证 获取出生日期、性别、年龄
function idCard (idCard) {
    var json = {};
    //获取出生日期
    let birth = getBirthdatByIdNo(idCard);
    json['出生日期'] = birth;
    //获取性别
    if (parseInt(idCard.substr(16, 1)) % 2 == 1) {
        json['性别'] = "男";
    } else {
        json['性别'] = "女";
    }
    //获取年龄
    json['年龄'] = getAge(birth);
    return json;
}
// 判断文件类型
function judgeFileType (file) {
    var arrType = ["xls", "xlsx", "doc", "docx", "ppt", "pptx", "pdf", "txt", "jpeg", "jpg", "png", "gif", "rmvb", "mp4", "mkv", "avi", "3gp", "html"];
    if (file) {
        var fileType = file.substring(file.lastIndexOf(".") + 1);
        fileType = fileType.toLowerCase();
        var indexof = $.inArray(fileType, arrType);
        if (indexof == -1) {
            alert("上传文件格式错误!");
            return false;
        } else {
            return arrType[indexof];
        }
    }
}
/**
 * 获取url传参
 */
function getUrlParam (name) {
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
    let r;
    if (window.location.search) {
        r = window.location.search.substr(1).match(reg);
    } else {
        let index = window.location.hash.indexOf('?');
        r = window.location.hash.substr(index + 1).match(reg)
    }
    if (r != null) {
        return decodeURI(r[2]);
    }
    return null;
}
// 获取页面链接参数
function getUrlParam (name) {
    var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
    if (!results) {
        return '';
    }
    return decodeURIComponent(results[1]) || '';
};
//获取url参数，支持#
function GetQueryString (name) {
    const { href } = window.location;
    var regExp = new RegExp(`([?|&]${name}=.*?)(?=&|#|$)`, 'ig');
    const r = href.match(regExp);
    if (!r) return null;
    const r2 = r.map(item => {
        return item.replace(new RegExp(`[?|&]${name}=`), '');
    });
    return decodeURIComponent(r2[0]);
}
// 获取url上的键值对
function getQueryString (name) {
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
    var r = window.location.search.substr(1).match(reg);
    if (r != null) return decodeURI(r[2]);
    return null;
}
// 自动下拉
// 参数：parent：绑定的input元素的父元素
//      limit：渲染最大数量
function autoFinish (parent, limit) {
    limit = limit || 6;
    var $input = null; //绑定的input元素
    var callback = () => { }; //选中下拉元素后的回调
    var auto = {
        el: '',
        created: false,
        init: function () {
            this.creatDom().bindEvent();
            this.created = true;
            return this;
        },
        // 生成智能提示弹框容器并初步给容器绑定事件
        creatDom: function () {
            if (this.created) return this;
            var that = this;
            var rootHtml = '<div class="autofinish_box"><ul></ul></div>';
            var style = '.autofinish_box{width:200px;max-height:300px;overflow-y:auto;position:absolute;background-color:#f9f9f9f9;z-index:9999}.autofinish_box li{padding:10px 5%;border-bottom:1px solid #e3e3e3;cursor: pointer; background:#f9f9f9;}.autofinish_box li:active{background-color:#e1e1e1}.autofinish_box li:hover{background-color:#e6e6e6;}';
            $('head').eq(0).append('<style>' + style + '</style>');
            $(parent).append(rootHtml);
            // 带你其他后隐藏
            $(document).on('click', function (e) {
                that.hide();
            });
            return this;
        },
        // 提前给智能提示框条目绑定点击事件，拿到相应的数据请求后端
        bindEvent: function () {
            if (this.created) return this;
            var that = this;
            // 代理绑定，由于还未渲染
            $(parent.children[parent.children.length - 1]).on('click', 'li', function (e) {
                var val = $(this).data('val');
                var showVal = $(this).data('show'); //显示值
                var index = $(this).data('index');
                val && $input.val(showVal).attr('upload', val);
                // 点击条目后隐藏
                setTimeout(function () {
                    that.hide();
                }, 30);
                typeof callback == 'function' && callback(showVal, val, index);
                e.stopPropagation();
            });
            return this;
        },
        // 计算智能体提示框位置宽高，移动父容器
        countOffset: function () {
            var elWidth = $input.get(0).offsetWidth;
            $('.autofinish_box').width(elWidth).css({
                top: $input.get(0).offsetHeight + 'px',
                left: 0 + 'px'
            });
            return this;
        },
        show: function () {
            $('.autofinish_box').show();
        },
        hide: function () {
            $('.autofinish_box').html('').hide();
            return this;
        },
        /*以上对内*/
        /*以下对外*/
        //用此方法的回调拿到点击条目dom上的数据去填补选后展示的数据
        bind: function (el, cb) {
            if (this.el && this.el == el) return this;
            callback = cb;
            el instanceof $ ? ($input = el) : ($input = $(el));
            $input.off('click').on('click', function (e) {
                e.stopPropagation();
            });
            // 当点击或切换不同input时重新计算位置
            this.countOffset();
            return this;
        },
        // 生成智能提示框内容
        renderList: function (res) {
            if (!res) return this;
            var list = [];
            for (var ii = 0; ii < res.length; ii++) {
                // 限制渲染的条目数量
                if (limit && limit <= ii) {
                    break;
                }
                list.push('<li data-val="' + res[ii].val + '" data-index="' + ii + '" data-show="' + res[ii].showVal + '" style="font-size:.16rem">' + res[ii].showVal + '</li>');
            }
            $(parent.children[parent.children.length - 1]).html(list.join('')).show();
            return this;
        }
    };
    auto.init();
    return auto;
}



// 节流
function debounce (fn, delay) {
    var timer
    return function () {
        var context = this
        var args = arguments
        clearTimeout(timer)
        timer = null
        timer = setTimeout(function () {
            fn.apply(context, args)
        }, delay)
    }
}
// 节流
function throttle (func, wait) {
    let previous = 0;
    return function () {
        let now = Date.now();
        let context = this;
        let args = arguments;
        if (now - previous > wait) {
            func.apply(context, args);
            previous = now;
        }
    }
}
// 获取数组极值
function smallest (array) {
    return Math.min.apply(Math, array);
}

function largest (array) {
    return Math.max.apply(Math, array);
}
// 判断小数是否相等epsEqu(0.1 + 0.2, 0.3)
function epsEqu (x, y) {
    return Math.abs(x - y) < Math.pow(2, -52);
}

function epsEqu (x, y) {
    return Math.abs(x - y) < Number.EPSILON;
}
// 清除空格
function trim (str) {
    var reExtraSpace = /^\s*(.*?)\s+$/;
    return str.replace(reExtraSpace, "$1");
}

function jsonToStr (obj) {
    if (typeof obj == "object") {
        var arr = new Array();
        for (var i in obj) {
            arr.push(i + ":" + jsonToStr(obj[i]));
        }
        return "{" + arr.join(",") + "}";
    } else {
        return "'" + obj + "'";
    }
}

function strToJson (str) {
    return eval("(" + str + ")");
}
/**
 * 判断一个字符串是不是IP地址的格式
 */
function isIP (str) {
    var arr = str.split(".");
    if (arr.length != 4) {
        return false;
    }
    for (var i = 0; i < arr.length; i++) {
        if (isInt(arr[i]) == false || arr[i].length > 3) {
            return false;
        }
        var num = parseInt(arr[i]);
        if (num < 0 || num > 255) {
            return false;
        }
    }
    return true;
}
/**
 *	判断一个字符串是否为正确的MAC格式
 */
function isMAC (str) {
    var reg = /^[0-9,a-f,A-F]{2}[-][0-9,a-f,A-F]{2}[-][0-9,a-f,A-F]{2}[-][0-9,a-f,A-F]{2}[-][0-9,a-f,A-F]{2}[-][0-9,a-f,A-F]{2}$/;
    return reg.test(str);
}
/**
 * 判断一个字符串是否为邮箱
 */
function isEmail (str) {
    if (str.length > 0) {
        var pattern = /^\w+@\w+(\.\w+)*$/;
        return pattern.test(str);
    }
    return false;
}
/**
 * 正则验证email格式
 * */
function checkEmail (mail) {
    var em = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
    if (!em.test(mail)) {
        return false;
    }
    return true;
}
// 检查邮箱
function checkEmail (myemail) {
    var myReg = /^[a-zA-Z0-9_-]+@([a-zA-Z0-9]+\.)+(com|cn|net|org)$/;
    if (myReg.test(myemail)) {
        return true;
    } else {
        return false;
    }
}

function checkEmail (myemail) {
    var myReg = /^[a-zA-Z0-9_-]+@([a-zA-Z0-9]+\.)+(com|cn|net|org)$/;
    if (myReg.test(myemail)) {
        return true;
    } else {
        return false;
    }
}
//判断是否符合电话号码格式
function isTel (str) {
    var reg = /^([0-9]|[\-])+$/g;
    if (str.length < 7 || str.length > 18) {
        return false;
    } else {
        return reg.test(str);
    }
}
/**
 * 正则验证手机号码
 * */
function checkMobile (mobile) {
    //    var m = /^1[0-9]{2}\d{4,8}$/;
    var m = /^1\d{10}$/;
    if (!m.test(mobile)) {
        return false;
    }
    return true;
}
// 检查手机号码
function checkPhone (phone) {
    if (!(/^1[34578]\d{9}$/.test(phone))) {
        return false;
    } else {
        return true;
    }
}
//身份证号码验证
function checkIdCard (id) {
    if (id) {
        //身份证的地区代码对照
        let aCity = {
            11: "北京",
            12: "天津",
            13: "河北",
            14: "山西",
            15: "内蒙古",
            21: "辽宁",
            22: "吉林",
            23: "黑龙江",
            31: "上海",
            32: "江苏",
            33: "浙江",
            34: "安徽",
            35: "福建",
            36: "江西",
            37: "山东",
            41: "河南",
            42: "湖北",
            43: "湖南",
            44: "广东",
            45: "广西",
            46: "海南",
            50: "重庆",
            51: "四川",
            52: "贵州",
            53: "云南",
            54: "西藏",
            61: "陕西",
            62: "甘肃",
            63: "青海",
            64: "宁夏",
            65: "新疆",
            71: "台湾",
            81: "香港",
            82: "澳门",
            91: "国外"
        };
        //获取证件号码
        let person_id = id;
        //合法性验证
        let sum = 0;
        //出生日期
        let birthday;
        //验证长度与格式规范性的正则
        let pattern = new RegExp(/(^\d{15}$)|(^\d{17}(\d|x|X)$)/i);
        if (pattern.exec(person_id)) {
            //验证身份证的合法性的正则
            pattern = new RegExp(/^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$/);
            if (pattern.exec(person_id)) {
                //获取15位证件号中的出生日期并转位正常日期
                birthday = "19" + person_id.substring(6, 8) + "-" + person_id.substring(8, 10) + "-" + person_id.substring(10, 12);
            } else {
                person_id = person_id.replace(/x|X$/i, "a");
                //获取18位证件号中的出生日期
                birthday = person_id.substring(6, 10) + "-" + person_id.substring(10, 12) + "-" + person_id.substring(12, 14);
                //校验18位身份证号码的合法性
                for (let i = 17; i >= 0; i--) {
                    sum += (Math.pow(2, i) % 11) * parseInt(person_id.charAt(17 - i), 11);
                }
                if (sum % 11 != 1) {
                    return false;
                }
            }
            //检测证件地区的合法性
            if (aCity[parseInt(person_id.substring(0, 2))] == null) {
                return false;
            }
            let dateStr = new Date(birthday.replace(/-/g, "/"));
            if (birthday != dateStr.getFullYear() + "-" + Append_zore(dateStr.getMonth() + 1) + "-" + Append_zore(dateStr.getDate())) {
                return false;
            }
        } else {
            return false;
        }
    } else {
        return false;
    }
    return true;
}
/**
 * 正则验证身份证号码
 * */
function checkIdenCode (code) {
    var city = { 11: "北京", 12: "天津", 13: "河北", 14: "山西", 15: "内蒙古", 21: "辽宁", 22: "吉林", 23: "黑龙江 ", 31: "上海", 32: "江苏", 33: "浙江", 34: "安徽", 35: "福建", 36: "江西", 37: "山东", 41: "河南", 42: "湖北 ", 43: "湖南", 44: "广东", 45: "广西", 46: "海南", 50: "重庆", 51: "四川", 52: "贵州", 53: "云南", 54: "西藏 ", 61: "陕西", 62: "甘肃", 63: "青海", 64: "宁夏", 65: "新疆", 71: "台湾", 81: "香港", 82: "澳门", 91: "国外 " };
    var tip = "";
    var pass = true;
    if (!code || !/^\d{6}(18|19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i.test(code)) {
        tip = "身份证号格式错误";
        pass = false;
    } else if (!city[code.substr(0, 2)]) {
        tip = "地址编码错误";
        pass = false;
    } else {
        //18位身份证需要验证最后一位校验位
        if (code.length == 18) {
            code = code.split('');
            //∑(ai×Wi)(mod 11)
            //加权因子
            var factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
            //校验位
            var parity = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2];
            var sum = 0;
            var ai = 0;
            var wi = 0;
            for (var i = 0; i < 17; i++) {
                ai = code[i];
                wi = factor[i];
                sum += ai * wi;
            }
            var last = parity[sum % 11];
            if (parity[sum % 11] != code[17]) {
                tip = "校验位错误";
                pass = false;
            }
        }
    }
    return pass;
}
/**
 * 正则验证微信号，不少于6位，以字母开头，只能包含字母、数字、下划线和减号
 * */
function checkWeiXinNum (str) {
    var em = /^[a-zA-Z][a-zA-Z0-9_-]{5,}$/;
    if (!em.test(str)) {
        return false;
    }
    return true;
}
/**
 * 判断一个字符串是不是 "2000-01-01 01:01:01" 这样的格式
 */
function isDateTimeString (str) {
    var pattern = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/;
    if (pattern.test(str) == false) {
        return false;
    }
    if (RegExp.$2 > 12) {
        return false;
    }
    if (RegExp.$3 > 31) {
        return false;
    }
    if (RegExp.$4 > 23) {
        return false;
    }
    if (RegExp.$5 > 59) {
        return false;
    }
    if (RegExp.$6 > 59) {
        return false;
    }
    return true;
}
/**
 * 判断一个字符串是不是 "2000-01-01" 这样的格式
 */
function isDateString (str) {
    var pattern = /^(\d{4})-(\d{2})-(\d{2})$/;
    if (pattern.test(str) == false) {
        return false;
    }
    if (RegExp.$2 > 12) {
        return false;
    }
    if (RegExp.$3 > 31) {
        return false;
    }
    return true;
}
/**
 * 判断一个字符串是不是 "01:01:01" 这样的格式
 */
function isTimeString (str) {
    var pattern = /^(\d{2}):(\d{2}):(\d{2})$/;
    if (pattern.test(str) == false) {
        return false;
    }
    if (RegExp.$1 > 23) {
        return false;
    }
    if (RegExp.$2 > 59) {
        return false;
    }
    if (RegExp.$3 > 59) {
        return false;
    }
    return true;
}
//判断起末日期是否在同年同月
function checkCommonMonth (startMonthId, endMonthId) {
    var start = $("#" + startMonthId).val();
    var end = $("#" + endMonthId).val();
    var startDate = start.substr(0, 7);
    var endDate = end.substr(0, 7);
    var flag = false;
    if (startDate == endDate) {
        flag = true;
    } else {
        alert("起始日期与结束日期必须同月！");
        flag = false;
    }
    return flag;
}
//获取上一个月的第一天
function getStartMonth () {
    var now = new Date();
    now.setMonth(now.getMonth() - 1);
    var date = "01";
    var month = now.getMonth() + 1;
    if (month < 10) {
        month = "0" + month;
    }
    return now.getFullYear() + "-" + month + "-" + date;
}
//获取上一个月的最后一天
function getEndMonth () {
    var now = new Date();
    now.setDate("01");
    now.setDate(now.getDate() - 1);
    var month = now.getMonth() + 1;
    if (month < 10) {
        month = "0" + month;
    }
    return now.getFullYear() + "-" + month + "-" + now.getDate();
}
/**
 * 进行url编码
 */
function doURLEncode (str) {
    if (str == null) {
        return null;
    }
    return encodeURIComponent(str).replaceAll("-", "%2D").replaceAll("%", "-");
}
/**
 * 进行url解码
 */
function doURLDecode (str) {
    if (str == null) {
        return null;
    }
    return decodeURIComponent(str.replaceAll("-", "%"));
}
/**
 * 计算两个日期间的工作日（只除去周末）
 *
 * @param sDay(string)
 * @param eDay(string)
 * @returns
 */
function countWorkDay (sDay, eDay) {
    var sDay = new Date(Date.parse(sDay.replace(/-/g, "/")));
    var eDay = new Date(Date.parse(eDay.replace(/-/g, "/")));
    var s_t_w = sDay.getDay(),
        e_t_w = eDay.getDay();
    // 总相差天数
    var diffDay = (eDay - sDay) / (1000 * 60 * 60 * 24) + 1;
    if (parseInt(diffDay) == 0) return parseInt(diffDay);
    // 周末天数
    var weekEnds = 0;
    for (var i = 0; i < diffDay; i++) {
        if (sDay.getDay() == 0 || sDay.getDay() == 6) weekEnds++;
        sDay = sDay.valueOf();
        sDay += 1000 * 60 * 60 * 24;
        sDay = new Date(sDay);
    }
    return parseInt(diffDay - weekEnds);
}
/**
 * 说明:
 * 		若 numToString( 123456789, 4 )
 * 		将 125369 转化为 5369
 *
 * 		若 numToString( 89, 4 )
 * 		将 89 转化为 0089
 *
 * 		获得最右边的4位,不足的用0来补.
 *
 * @param num
 * 		要进行转化的数
 * @param len
 * 		要输出的数的位数
 * @return
 */
function numToString (num, len) {
    var s = "" + num;
    var slen = s.length;
    if (slen > len) {
        return s.substring(s.length - len);
    }
    if (slen < len) {
        var count = len - slen;
        var arr = [];
        for (var i = 0; i < count; i++) {
            arr.push("0");
        }
        return arr.join("") + s;
    }
    return s;
}
/**
 * 截断字符串
 */
function getSkipSubstring (str, len) {
    if (str.length < len) {
        return str;
    } else {
        str = str.substring(0, len) + "...";
    }
    return str;
}

function cutstr (str, length) {
    var temp;
    var icount = 0;
    var patrn = /[^\x00-\xff]/;
    var strre = "";
    for (var i = 0; i < str.length; i++) {
        if (icount < len - 1) {
            temp = str.substr(i, 1);
            if (patrn.exec(temp) == null) {
                icount = icount + 1;
            } else {
                icount = icount + 2;
            }
            strre += temp;
        } else {
            break;
        }
    }
    return strre + "...";
}
/**
 * 转义html标签
 */
function htmlEncode (text) {
    return text.replace(/&/g, '&').replace(/\"/g, '"').replace(/</g, '<').replace(/>/g, '>');
}
/**
 * 还原html标签
 */
function htmlDecode (text) {
    return text.replace(/&/g, '&').replace(/"/g, '\"').replace(/</g, '<').replace(/>/g, '>');
}
/**
 * 动态加载 CSS 样式文件
 */
function LoadStyle (url) {
    try {
        document.createStyleSheet(url);
    } catch (e) {
        var cssLink = document.createElement('link');
        cssLink.rel = 'stylesheet';
        cssLink.type = 'text/css';
        cssLink.href = url;
        var head = document.getElementsByTagName('head')[0];
        head.appendChild(cssLink);
    }
}
/**
 * 返回浏览器版本
 * 返回一个对象,对象属性：type，version
 */
function getExplorerInfo () {
    var explorer = window.navigator.userAgent.toLowerCase();
    // ie
    if (explorer.indexOf("msie") >= 0) {
        var ver = explorer.match(/msie ([\d.]+)/)[1];
        return {
            type: "IE",
            version: ver
        };
    }
    // firefox
    else if (explorer.indexOf("firefox") >= 0) {
        var ver = explorer.match(/firefox\/([\d.]+)/)[1];
        return {
            type: "Firefox",
            version: ver
        };
    }
    // Chrome
    else if (explorer.indexOf("chrome") >= 0) {
        var ver = explorer.match(/chrome\/([\d.]+)/)[1];
        return {
            type: "Chrome",
            version: ver
        };
    }
    // Opera
    else if (explorer.indexOf("opera") >= 0) {
        var ver = explorer.match(/opera.([\d.]+)/)[1];
        return {
            type: "Opera",
            version: ver
        };
    }
    // Safari
    else if (explorer.indexOf("Safari") >= 0) {
        var ver = explorer.match(/version\/([\d.]+)/)[1];
        return {
            type: "Safari",
            version: ver
        };
    }
}
// 返回IE浏览器的版本号
function getIE () {
    if (window.ActiveXObject) {
        var v = navigator.userAgent.match(/MSIE ([^;]+)/)[1];
        return parseFloat(v.substring(0, v.indexOf(".")));
    }
    return false;
}
// 与insertBefore方法（已存在）对应的insertAfter方法
function insertAfter (newChild, refChild) {
    var parElem = refChild.parentNode;
    if (parElem.lastChild == refChild) {
        refChild.appendChild(newChild);
    } else {
        parElem.insertBefore(newChild, refChild.nextSibling);
    }
}
/**
 * 获取页面高度
 */
function getPageHeight () {
    var g = document,
        a = g.body,
        f = g.documentElement,
        d = g.compatMode == "BackCompat" ? a : g.documentElement;
    return Math.max(f.scrollHeight, a.scrollHeight, d.clientHeight);
}
/**
 * 获取页面宽度
 */
function getPageWidth () {
    var g = document,
        a = g.body,
        f = g.documentElement,
        d = g.compatMode == "BackCompat" ? a : g.documentElement;
    return Math.max(f.scrollWidth, a.scrollWidth, d.clientWidth);
}
/**
 * 获取页面scrollLeft
 */
function getPageScrollLeft () {
    var a = document;
    return a.documentElement.scrollLeft || a.body.scrollLeft;
}
/**
 * 获取页面scrollTop
 */
function getPageScrollTop () {
    var a = document;
    return a.documentElement.scrollTop || a.body.scrollTop;
}
/**
 * 获取页面可视高度
 */
function getPageViewHeight () {
    var d = document,
        a = d.compatMode == "BackCompat" ? d.body : d.documentElement;
    return a.clientHeight;
}
/**
 * 完美判断是否为网址
 */
function IsURL (strUrl) {
    var regular = /^\b(((https?|ftp):\/\/)?[-a-z0-9]+(\.[-a-z0-9]+)*\.(?:com|edu|gov|int|mil|net|org|biz|info|name|museum|asia|coop|aero|[a-z][a-z]|((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]\d)|\d))\b(\/[-a-z0-9_:\@&?=+,.!\/~%\$]*)?)$/i;
    if (regular.test(strUrl)) {
        return true;
    } else {
        return false;
    }
}
/**
 * 判断是否Touch屏幕
 */
function isTouchScreen () {
    return (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch);
}
/**
 * 格式化CSS样式代码
 */
function formatCss (s) { // 格式化代码
    s = s.replace(/\s*([\{\}\:\;\,])\s*/g, "$1");
    s = s.replace(/;\s*;/g, ";"); // 清除连续分号
    s = s.replace(/\,[\s\.\#\d]*{/g, "{");
    s = s.replace(/([^\s])\{([^\s])/g, "$1 {\n\t$2");
    s = s.replace(/([^\s])\}([^\n]*)/g, "$1\n}\n$2");
    s = s.replace(/([^\s]);([^\s\}])/g, "$1;\n\t$2");
    return s;
}
/**
 * 压缩CSS样式代码
 */
function yasuoCss (s) { // 压缩代码
    s = s.replace(/\/\*(.|\n)*?\*\//g, ""); // 删除注释
    s = s.replace(/\s*([\{\}\:\;\,])\s*/g, "$1");
    s = s.replace(/\,[\s\.\#\d]*\{/g, "{"); // 容错处理
    s = s.replace(/;\s*;/g, ";"); // 清除连续分号
    s = s.match(/^\s*(\S+(\s+\S+)*)\s*$/); // 去掉首尾空白
    return (s == null) ? "" : s[1];
}
/**
 * 光标停在文字的后面，文本框获得焦点时调用
 */
function focusLast () {
    var e = event.srcElement;
    var r = e.createTextRange();
    r.moveStart('character', e.value.length);
    r.collapse(true);
    r.select();
}
/**
 * ip 转 整型
 */
function _ip2int (ip) {
    var num = 0;
    ip = ip.split(".");
    num = Number(ip[0]) * 256 * 256 * 256 + Number(ip[1]) * 256 * 256 + Number(ip[2]) * 256 + Number(ip[3]);
    num = num >>> 0;
    return num;
}
/**
 * 整型解析为IP地址
 */
function _int2iP (num) {
    var str;
    var tt = new Array();
    tt[0] = (num >>> 24) >>> 0;
    tt[1] = ((num << 8) >>> 24) >>> 0;
    tt[2] = (num << 16) >>> 24;
    tt[3] = (num << 24) >>> 24;
    str = String(tt[0]) + "." + String(tt[1]) + "." + String(tt[2]) + "." + String(tt[3]);
    return str;
}
//处理中文字符和英文字符长度（'我'.length==1）（len('我')==2）s
function len (s) {
    var l = 0;
    var a = s.split("");
    for (var i = 0; i < a.length; i++) {
        if (a[i].charCodeAt(0) < 299) {
            l++;
        } else {
            l += 2;
        }
    }
    return l;
}
/**************************
 * 字符串转换成xml格式：
 *  strXml : 字符串xml
 ***************************/
function FormatToXml (strXml) {
    var isIE = function () {
        var IE = /msie/i.test(navigator.userAgent);
        return IE;
    }
    var Exc = function () {
        var XmlDoc = null;
        if (isIE()) {
            XmlDoc = new ActiveXObject("Microsoft.XMLDOM");
            XmlDoc.loadXML(strXml);
        } else {
            XmlDoc = (new DOMParser()).parseFromString(strXml, "text/xml");
        }
        return XmlDoc;
    }
    return Exc();
}
//两种调用方式
//	var template1="我是{0}源码天空，今年{1}了";
//	var template2="我是{name}，今年{age}了";
//	var result1=template1.format("loogn",22);
//	var result2=template1.format({name:"loogn",age:22});
//两个结果都是"我是loogn，今年22了"
String.prototype.format = function (args) {
    if (arguments.length > 0) {
        var result = this;
        if (arguments.length == 1 && typeof (args) == "object") {
            for (var key in args) {
                var reg = new RegExp("({" + key + "})", "g");
                result = result.replace(reg, args[key]);
            }
        } else {
            for (var i = 0; i < arguments.length; i++) {
                if (arguments[i] == undefined) {
                    return "";
                } else {
                    var reg = new RegExp("({[" + i + "]})", "g");
                    result = result.replace(reg, arguments[i]);
                }
            }
        }
        return result;
    } else {
        return this;
    }
}

function clone (obj) {
    var o, obj;
    if (obj.constructor == Object) {
        o = new obj.constructor();
    } else {
        o = new obj.constructor(obj.valueOf());
    }
    for (var key in obj) {
        if (o[key] != obj[key]) {
            if (typeof (obj[key]) == 'object') {
                o[key] = clone(obj[key]);
            } else {
                o[key] = obj[key];
            }
        }
    }
    o.toString = obj.toString;
    o.valueOf = obj.valueOf;
    return o;
};
//两个时间相差天数 兼容firefox chrome
function datedifference (sDate1, sDate2) { //sDate1和sDate2是2006-12-18格式
    var dateSpan,
        tempDate,
        iDays;
    sDate1 = Date.parse(sDate1);
    sDate2 = Date.parse(sDate2);
    dateSpan = sDate2 - sDate1;
    dateSpan = Math.abs(dateSpan);
    iDays = Math.ceil(dateSpan / (24 * 3600 * 1000));
    return iDays
};

//日期比较时间大小
function compareTime (firstTime, secondTime) {
    var d1 = new Date((firstTime + '').replace(/\-/g, "\/"));
    var d2 = new Date((secondTime + '').replace(/\-/g, "\/"));
    if (firstTime != "" && secondTime != "" && d1 >= d2) {
        //firstTime > secondTime
        return true;
    } else {
        return false;
    }
}

function renderFileType (filetype) {
    switch (filetype) {
        case 'image/png':
        case 'image/jpeg':
        case 'image/bmp':
            return 'image';
        case 'application/msword':
        case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
            return 'word';
        case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
            return 'xlsx';
        case 'application/zip':
        case 'application/java-archive':
        case 'application/x-zip-compressed':
            return 'zip';
        case 'audio/mpeg':
        case 'audio/mp3':
            return "mp3";
        case 'video/mp4':
        case 'video/x-msvideo':
        case 'video/x-ms-wmv':
            return "video";
        default:
            return "file";
    }
}
// 在除了 IE 的浏览器下，直接这样写：
// var date = new Date("2011-11-07");
// IE 下 date 会是 NaN，所以用下法替代：
//解决IE下new Date()不能传参数问题
function newDateAndTime (dateStr) {
    var ds = dateStr.split(" ")[0].split("-");
    var ts = dateStr.split(" ")[1].split(":");
    var date = new Date();
    date.setFullYear(ds[0], ds[1] - 1, ds[2]);
    date.setHours(ts[0], ts[1], ts[2], 0);
    return date;
}

function NewDate (str) {
    str = str.split('-');
    var date = new Date();
    date.setUTCFullYear(str[0], str[1] - 1, str[2]);
    date.setUTCHours(0, 0, 0, 0);
    return date;
}
//计算两个日期的天数差
function dateDiff (firstDate, secondDate) {
    var firstDate = new Date(firstDate);
    var secondDate = new Date(secondDate);
    var diff = Math.abs(firstDate.getTime() - secondDate.getTime())
    var result = parseInt(diff / (1000 * 60 * 60 * 24));
    return result
}
/**
*date为开始日期，dayLength是相隔的天数，可以为负数；（可跨年）
  date：yyyy-MM-dd
*/
function getTargetDate (date, dayLength) {
    var tempDate = new Date(date);
    tempDate.setDate(tempDate.getDate() + dayLength);
    var year = tempDate.getFullYear();
    var month = tempDate.getMonth() + 1 < 10 ? "0" + (tempDate.getMonth() + 1) : tempDate.getMonth() + 1;
    var day = tempDate.getDate() < 10 ? "0" + tempDate.getDate() : tempDate.getDate();
    return year + "-" + month + "-" + day;
}
// 计算相隔天数的日期
// dataStr：yyyy-MM-dd HH:mm:ss
// datas：20(number)
function getLimitDate (dateStr, dates) {
    var date = newDateAndTime(dateStr);
    date.setDate(date.getDate() + dates);
    return date.format('yyyy-MM-dd HH:mm:ss');
}
// 车牌号正则
function testPlate () {
    if (!(/^([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[a-zA-Z](([DF]((?![IO])[a-zA-Z0-9](?![IO]))[0-9]{4})|([0-9]{5}[DF]))|[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1})$/.test(plate))) {
        alert('车牌号格式不正确');
        return false;
    }
}
// 将RGBA颜色转换为16进制的颜色转换后无透明度，适合IE8
// var myHex = hexify('rgba(255,232,186,0.4)'); // "#f5faf3"
function hexify (color) {
    var values = color.replace(/rgba?\(/, '').replace(/\)/, '').replace(/[\s+]/g, '').split(',');
    var a = parseFloat(values[3] || 1),
        r = Math.floor(a * parseInt(values[0]) + (1 - a) * 255),
        g = Math.floor(a * parseInt(values[1]) + (1 - a) * 255),
        b = Math.floor(a * parseInt(values[2]) + (1 - a) * 255);
    return "#" + ("0" + r.toString(16)).slice(-2) + ("0" + g.toString(16)).slice(-2) + ("0" + b.toString(16)).slice(-2);
}
/**
 * rgb转rgba
 * @param color
 * @param alp
 * @returns {string}
 */
function rgbToRgba (color, alp) {
    var r, g, b;
    var rgbaAttr = color.match(/[\d.]+/g);
    if (rgbaAttr.length >= 3) {
        var r, g, b;
        r = rgbaAttr[0];
        g = rgbaAttr[1];
        b = rgbaAttr[2];
        return 'rgba(' + r + ',' + g + ',' + b + ',' + alp + ')';
    }
}
/**
 * rgba转rgb，直接移除透明度
 * @param color
 * @returns {string}
 */
function rgbaToRgb (color) {
    var rgbaAttr = color.match(/[\d.]+/g);
    if (rgbaAttr.length >= 3) {
        var r, g, b;
        r = rgbaAttr[0];
        g = rgbaAttr[1];
        b = rgbaAttr[2];
        return 'rgb(' + r + ',' + g + ',' + b + ')';
    }
    return '';
}
/**
 * 获取rgba中的透明度
 * @param color
 * @returns {number}
 */
function getRgbaAlp (color) {
    var alp = 1;
    var rgbaReg = /rgba\([\d ]+(?:\,([\d. ]+)){3}\)/;
    if (rgbaReg.test(color)) {
        alp = color.replace(rgbaReg, '$1');
    }
    return alp;
}
/*16进制颜色值转化rgb
  hex: {String}, "#333", "#AF0382"
  console.log(hexToRgb("#555"));
  console.log(hexToRgb("#AF3823"));
  输出如下
  {r: 85, g: 85, b: 85}
  {r: 175, g: 56, b: 35}
*/
function hexToRgb (hex) {
    hex = hex.slice(1);
    if (hex.length == 3) {
        hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
    }
    return 'rgb(' + Number.parseInt(hex.slice(0, 2), 16) + ',' + Number.parseInt(hex.slice(2, 4), 16) + ',' + Number.parseInt(hex.slice(4, 6), 16) + ')';
}
// 16进制颜色值转化rgba
// colorRgba('#f00',0.2)使用正则
function colorRgba (sHex, alpha = 0.15) {
    // 十六进制颜色值的正则表达式
    var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
    /* 16进制颜色转为RGB格式 */
    let sColor = sHex.toLowerCase()
    if (sColor && reg.test(sColor)) {
        if (sColor.length === 4) {
            var sColorNew = '#'
            for (let i = 1; i < 4; i += 1) {
                sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1))
            }
            sColor = sColorNew
        }
        //  处理六位的颜色值
        var sColorChange = []
        for (let i = 1; i < 7; i += 2) {
            sColorChange.push(parseInt('0x' + sColor.slice(i, i + 2)))
        }
        // return sColorChange.join(',')
        // 或
        return 'rgba(' + sColorChange.join(',') + ',' + alpha + ')'
    } else {
        return sColor
    }
}
// RGBToHex('rgba(255,255,255,0.3)')
// {color: "#ffffff", opacity: 30}
function RGBToHex (rgba) {
    let str = rgba.slice(5, rgba.length - 1),
        arry = str.split(','),
        opa = Number(arry[3].trim()) * 100,
        strHex = "#",
        r = Number(arry[0].trim()),
        g = Number(arry[1].trim()),
        b = Number(arry[2].trim());
    strHex += ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
    return { color: strHex, opacity: opa };
}
// HexToRGB("#ffffff", 30);
// "rgba(255, 255, 255, 0.3)"
function HexToRGB (color, opacity) {
    let newColor = 'rgba(';
    //判断是三位还是六位
    if (color.length === 4) {
        let arry = [];
        for (let i = 1; i < color.length; i++) {
            arry.push(parseInt("0x" + color[i] + color[i]));
        }
        arry.forEach(function (item) {
            newColor += item + ', ';
        });
        newColor += opacity / 100 + ')';
        return newColor;
    } else {
        let arry = [];
        for (let i = 1; i < color.length; i += 2) {
            arry.push(parseInt("0x" + color.slice(i, i + 2)));
        }
        arry.forEach(function (item) {
            newColor += item + ', ';
        });
        newColor += opacity / 100 + ')';
        return newColor;
    }
}
// 正则检测rgba格式是否正确，支持rgba直接写.1（255,255,255,.2）不存在这种写法（.3,0.3,2.1），只能是整数
function checkRGBA (rgba) {
    let str = rgba.slice(5, rgba.length - 1),
        arry = str.split(','),
        status = true,
        reg = /^rgba\(\d{1,3}(\,\s{0,1}\d{1,3}){2}\,\s{0,1}(0|(0?(\.\d{1,2}))|1)\)$/;
    arry.forEach(function (item, index) {
        if (/^(\.\*)/.test(item)) {
            item = item + 0;
        }
        if (index == arry.length - 1) {
            if (Number(item.trim()) < 0 || Number(item.trim()) > 1) {
                status = false;
            }
        } else {
            if (Number(item.trim()) < 0 || Number(item.trim()) > 255) {
                status = false;
            }
        }
    });
    if (reg.test(rgba) && status) {
        return true;
    } else {
        return false;
    }
}
// 正则检测rgb格式是否正确
function checkRGB (rgb) {
    let str = rgb.slice(5, rgb.length - 1),
        arry = str.split(','),
        status = true,
        reg = /^rgb\(\d{1,3}(\,\s{0,1}\d{1,3}){2}\)$/;
    arry.forEach(function (item, index) {
        if (Number(item.trim()) < 0 || Number(item.trim()) > 255) {
            status = false;
        }
    });
    if (reg.test(rgb) && status) {
        return true;
    } else {
        return false;
    }
}
// 手机端判断浏览器类型
BrowserInfo = {
    isAndroid: Boolean(navigator.userAgent.match(/android/ig)),
    isIphone: Boolean(navigator.userAgent.match(/iphone|ipod/ig)),
    isIpad: Boolean(navigator.userAgent.match(/ipad/ig)),
    isWeixin: Boolean(navigator.userAgent.match(/MicroMessenger/ig)),
    isAli: Boolean(navigator.userAgent.match(/AlipayClient/ig)),
    isPhone: Boolean(/(iPhone|iPad|iPod|iOS|Android)/i.test(navigator.userAgent))
}
// 递归深拷贝
function deepClone (obj) {
    function isClass (o) {
        if (o === null) return "Null";
        if (o === undefined) return "Undefined";
        return Object.prototype.toString.call(o).slice(8, -1);
    }
    var result;
    var oClass = isClass(obj);
    if (oClass === "Object") {
        result = {};
    } else if (oClass === "Array") {
        result = [];
    } else {
        return obj;
    }
    for (var key in obj) {
        var copy = obj[key];
        if (isClass(copy) == "Object") {
            result[key] = arguments.callee(copy); //递归调用
        } else if (isClass(copy) == "Array") {
            result[key] = arguments.callee(copy);
        } else {
            result[key] = obj[key];
        }
    }
    return result;
}
/**
 * 校验起止日期要小于结束日期
 * @param beginDateID 开始日期id
 * @param endDateID 结束日期id
 * @returns {Boolean}，true开始日期小于结束日期，false相反
 */
function dateCompare (beginDateID, endDateID) {
    var flag = true;
    var beginDate = $('#' + beginDateID).val();
    var endDate = $('#' + endDateID).val();
    if (beginDate && endDate) {
        var beginArray = beginDate.split("-");
        var endArray = endDate.split("-");
        var beginTime = beginArray[0] + "/" + beginArray[1] + "/" + beginArray[2];
        var endTime = endArray[0] + "/" + endArray[1] + "/" + endArray[2];
        if (beginTime > endTime) {
            alert("起始日期不能大于结束日期！");
            flag = false;
        } else {
            flag = true;
        }
    }
    return flag;
}
/**
 * 禁止回车，禁止其他键同理
 * @param id 待禁止元素id
 */
function forbidKeydown (id) {
    $("#" + id).bind('keydown', function (event) {
        if (event.keyCode == 13) {
            event.keyCode = 0;
            return false;
        }
    });
}
/*7手机端收起弹出键盘*/
var hideKeyboard = function () {
    document.activeElement.blur(); //ios
    $("input").blur();
};
/*
 * JSON数组去重
 * @param: [array] json Array
 * @param: [string] 唯一的key名，根据此键名进行去重
 */
function uniqueArray (array, key) {
    var result = [array[0]];
    for (var i = 1; i < array.length; i++) {
        var item = array[i];
        var repeat = false;
        for (var j = 0; j < result.length; j++) {
            if (item[key] == result[j][key]) {
                repeat = true;
                break;
            }
        }
        if (!repeat) {
            result.push(item);
        }
    }
    return result;
}
//使用方法：
var _json = [{ id: 'aaa', name: 'bb' }, { id: 'bbb', name: 'xx' }, { id: 'aaa', name: 'ccc' }]
uniqueArray(_json, 'id');
/*14.获取当前时间的时间戳(三种方法)*/
var d1 = new Date().getTime();
var d2 = new Date().valueOf();
var d3 = +new Date();
// 高阶柯里化函数
function curryingHelper (fn, len) {
    const length = len || fn.length // 第一遍运行length是函数fn一共需要的参数个数，以后是剩余所需要的参数个数
    return function (...rest) {
        return rest.length >= length // 检查是否传入了fn所需足够的参数
            ? fn.apply(this, rest) : curryingHelper(currying.apply(this, [fn].concat(rest)), length - rest.length) // 在通用currying函数基础上
    }
}
/**
 * 函数反科里化：
 * 把一个签名如下的方法: obj.foo(arg1, arg2)，
 * 转换成另外一个签名如下的函数: foo(obj, arg1, arg2)
 */
function uncurryThis (func) {
    var call = Function.call;
    return function () {
        return call.apply(func, arguments);
    };
};
/**
 * 科里化this
 */
function curryThis (func) {
    return function () {
        var a = Array.prototype.slice.call(arguments);
        a.unshift(this);
        return func.apply(null, a);
    };
};
//  函数科里化
function curring (func) {
    return function () {
        var args = Array.prototype.slice.call(arguments, 0); //变成数组
        if (args.length < func.length) { // 如果实参参数个数小于形参个数，不能调用返回函数
            return function () {
                var _args = args.concat(Array.prototype.slice.call(arguments, 0)); // 取得参数
                return self.curring(func).apply(this, _args); // 然后递归调用函数,获取所有参数
            }
        } else {
            return func.apply(this, args);
        }
    }
};
// 偏函数是创建一个调用另外一个部分(参数或变量已预制的函数)的函数，函数可以根据传入的参数来生成一个真正执行的函数。比如：
// const isString = isType('String')
// const isFunction = isType('Function')
// 这样就用偏函数快速创建了一组判断对象类型的方法~
function isType (type) {
    return function (obj) {
        return Object.prototype.toString.call(obj) === `[object ${type}]`
    }
}
// 科里化延迟执行
function curry (fn) {
    var _args = [];
    return function cb () {
        var args = Array.prototype.slice.call(arguments, 0); //变成数组
        if (args.length === 0) { //关键点
            return fn.apply(this, _args)
        }
        _args.push.apply(_args, args)
        return cb
    }
}
var curryAdd = curry(function () {
    var args = Array.prototype.slice.call(arguments, 0); //变成数组
    alert(args.reduce(function (sum, single) { return sum += single }))
})
// curryAdd(1)
// curryAdd(2)
// curryAdd(3)
// curryAdd(4)
// curryAdd()               // 最后计算输出:10
//创建一个迭代器,按顺序执行多个异步函数
function MyIteration (arr) {
    var that = this;
    var num = 0;
    var len = arr.length;
    var fn = arr[num];
    fn.call(that, callback);
    //上一步执行的结果
    function callback () {
        num++;
        if (num < len) {
            var fn = arr[num];
            fn.call(that, callback);
        }
    }
}
// function a(next) {
//   setTimeout(function () {
//       alert(1);
//       next(); //执行下一个函数
//   }, 100);
// };
// function b(next) {
//   setTimeout(function () {
//       alert(2);
//       next(); //执行下一个函数
//   }, 300);
// };
// function c(next) {
//   setTimeout(function () {
//       alert(3);
//       next(); //执行下一个函数
//   }, 1000);
// };
// var arr = [a, b, c];//关键点每个函数有个参数用确定执行完成
// MyIteration(arr)
function Append_zore (temp) {
    if (temp < 10) {
        return "0" + temp;
    } else {
        return temp;
    }
}
/*判断空值*/
function isNull (item) {
    var ret = false;
    if (!item || item == '' || typeof (item) == 'undefined') {
        ret = true;
    }
    return ret;
}
//数字每3位加“,” 如：1,2222
function renderNum (num) {
    var ret = "";
    ret += num;
    if (num != null && num != '') {
        ret = ret.split("").reverse().join("").replace(/(\d{3})(?=[^$])/g, "$1,").split("").reverse().join("");
    }
    return ret;
}
//空字符串或者null转变为“--”
function renderNullToNotKnow (str) {
    if (str == null || str === "" || typeof (str) == "undefined" || str == "PLATE") {
        return "--";
    } else {
        return str;
    }
}

function thousandBitSeparator (num) {
    return num && num.toString().replace(/(\d)(?=(\d{3})+\.)/g, function ($0, $1) {
        return $1 + ",";
    });
}
/**
 * 获取本月的X轴描述
 * @returns {Array}
 */
function getXDescByMonth () {
    var desc = [];
    var date = new Date();
    var y = date.getFullYear();
    var m = date.getMonth() + 1;
    var endDay = new Date(y, m, 0).getDate();
    for (var i = 1; i <= endDay; i++) {
        desc.push(i + "号");
    }
    return desc;
}
/** 获取本月的结束日期**/
function getCurrentMonthEndTime () {
    var now = new Date(); //当前日期
    var nowDay = now.getDate(); //当前日
    var nowMonth = now.getMonth(); //当前月
    var nowYear = now.getYear(); //当前年
    nowYear += (nowYear < 2000) ? 1900 : 0;
    var monthStartDate = new Date(nowYear, nowMonth, 1);
    var monthEndDate = new Date(nowYear, nowMonth + 1, 1);
    var days = (monthEndDate - monthStartDate) / (1000 * 60 * 60 * 24);
    var getMonthEndDate = new Date(nowYear, nowMonth, days);
    var getMonthEndDate = getMonthEndDate.format("yyyy-MM-dd") + " 23:59:59";
    return getMonthEndDate;
}
// /** 获取本月的开始日期**/依赖dataformat.js
function getCurrentMonthStartTime () {
    var now = new Date(); //当前日期
    var nowDay = now.getDate(); //当前日
    var nowMonth = now.getMonth(); //当前月
    var nowYear = now.getYear(); //当前年
    nowYear += (nowYear < 2000) ? 1900 : 0;
    var getMonthStartDate = new Date(nowYear, nowMonth, 1);
    var getMonthStartDate = getMonthStartDate.format("yyyy-MM-dd") + " 00:00:00";
    return getMonthStartDate;
}
/**
 * 获取昨日的起始日期和结束日期(格式:yyyyMMddHH)
 * @return [beginTime,endTime]
 */
function getYestedDayBetween () {
    var now = new Date();
    now.add("day", -1);
    var beginTime = now.format("yyyyMMdd") + "00";
    var endTime = now.format("yyyyMMdd") + "23";
    return [beginTime, endTime];
}
/**
 * 获取本日的起始日期和结束日期(格式:yyyyMMddHH)
 * @return [beginTime,endTime]
 */
function getCurDayBetween () {
    var now = new Date();
    var beginTime = now.format("yyyyMMdd") + "00";
    var endTime = now.format("yyyyMMdd") + "23";
    return [beginTime, endTime];
}
/**
 * 获取本周的起始日期和结束日期(格式:yyyyMMdd)
 * @return [beginTime,endTime]
 */
function getCurWeekBetween () {
    var now = new Date();
    var _week = now.getUTCDay(); //0-6
    if (_week == 0) {
        _week = 7;
    }
    now.add("day", 7 - _week);
    var endTime = now.format("yyyyMMdd");
    now.add("day", -6);
    var beginTime = now.format("yyyyMMdd");
    return [beginTime, endTime];
}
/**
 * 获取本月的起始日期和结束日期(格式:yyyyMMdd)
 * @return [beginTime,endTime]
 */
function getCurMonthBetween () {
    var date = new Date();
    var y = date.getFullYear();
    var m = date.getMonth() + 1;
    var days = new Date(y, m, 0).getDate();
    m = (m <= 9) ? "0" + m : m + "";
    return [y + m + "01", y + m + days];
}
// 时间戳转时间
function timestampToTime (timestamp) {
    var date = new Date(timestamp);
    Y = date.getFullYear() + '-';
    M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
    D = (date.getDate() < 10) ? '0' + date.getDate() : date.getDate() + '';
    return Y + M + D;
}
// 获取指定日期的前一天
function getYesterday (date) {
    return timestampToTime(new Date(date).getTime() - 86400000);
}
/*'yyyy-MM-dd HH:mm:ss'格式的字符串转日期对象*/
function stringToDate (str) {
    var tempStrs = str.split("  ");
    var dateStrs = tempStrs[0].split("-");
    var year = parseInt(dateStrs[0], 10);
    var month = parseInt(dateStrs[1], 10) - 1;
    var day = parseInt(dateStrs[2], 10);
    var timeStrs = tempStrs[1].split(":");
    var hour = parseInt(timeStrs[0], 10);
    var minute = parseInt(timeStrs[1], 10);
    var second = parseInt(timeStrs[2], 10);
    var date = new Date(year, month, day, hour, minute, second);
    return date;
}
//获取交集
function intersectArr (prevArr, arr) {
    var result = new Array(),
        prevArrLen = prevArr.length,
        arrLen = arr.length,
        minArr = [],
        maxArr = [];
    if (prevArrLen <= arrLen) {
        minArr = prevArr;
        maxArr = arr;
    } else {
        minArr = arr;
        maxArr = prevArr;
    }
    for (var i = 0; i < minArr.length; i++) {
        var index = maxArr.indexOf(minArr[i]);
        if (index >= 0) {
            result.push(minArr[i]);
        }
    }
    return result;
}
// 交集
function array_intersection (a, b) {
    var result = [];
    for (var i = 0; i < b.length; i++) { var temp = b[i]; for (var j = 0; j < a.length; j++) { if (temp === a[j]) { result.push(temp); break; } } }
    return array_remove_repeat(result);
}
// 差集 a - b
function array_difference (a, b) {
    //clone = a
    var clone = a.slice(0);
    for (var i = 0; i < b.length; i++) {
        var temp = b[i];
        for (var j = 0; j < clone.length; j++) {
            if (temp === clone[j]) {
                //remove clone[j]
                clone.splice(j, 1);
            }
        }
    }
    return array_remove_repeat(clone);
}
// 去重
function array_remove_repeat (a) {
    var r = [];
    for (var i = 0; i < a.length; i++) {
        var flag = true;
        var temp = a[i];
        for (var j = 0; j < r.length; j++) {
            if (temp === r[j]) {
                flag = false;
                break;
            }
        }
        if (flag) {
            r.push(temp);
        }
    }
    return r;
}
// 并集
function array_union (a, b) { // 并集
    return array_remove_repeat(a.concat(b));
}
// 动态加载js后
function addScript (jsfile, callback) {
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = jsfile;
    head.appendChild(script);
    script.onload = script.onreadystatechange = function () {
        if (!this.readyState || this.readyState === "loaded" || this.readyState === "complete") {
            script.onload = script.onreadystatechange = null;
            if (callback && typeof (callback) == 'function') {
                callback(); //window[callback]();如果传递字符串过来  调用window['函数名']() 调用方法
            }
        }
    };
}
// 去除空格
function returnNoSpace (str) {
    return str.replace(/\s+/g, ' ');
}
// 判断有没有这属性
function hasPrototypeProperty (obj, pro) {
    //  hasOwnProperty   in
    if (!obj.hasOwnProperty(pro) && (pro in obj)) {
        return true;
    }
    return false;
}
/* 动态计算html标签的font-size,用于rem布局
  以iphone6为750基准，1rem = 100px，0.1rem = 10px
*/
(function () {
    var _;
    (_ = function () {
        document.querySelector('html').style.fontSize = 0.26667 * (750 <= document.documentElement.clientWidth ? 750 : document.documentElement.clientWidth) + "px";
    })();
    window.onresize = _;
})();
// 以640为基准
(function () {
    function resizeBaseFontSize () {
        var rootHtml = document.documentElement,
            deviceWidth = rootHtml.clientWidth;
        if (deviceWidth > 640) {
            deviceWidth = 640;
        }
        rootHtml.style.fontSize = deviceWidth / 7.5 + "px";
    }
    resizeBaseFontSize();
    window.addEventListener("resize", resizeBaseFontSize, false);
    window.addEventListener("orientationchange", resizeBaseFontSize, false);
})();
//替换指定传入参数的值
//win为某窗体,paramName为参数,paramValue为新值,forceAdding为不存在该参数时是否也指定
function replaceParamVal (win, paramName, paramValue, forceAdding) {
    var search = win.location.search + '';
    if (!search) { //没有任何查询参数,则直接附加
        return (forceAdding ? (win.location + '?' + paramName + '=' + paramValue) : (win.location + ''));
    } else {
        var q = (win.location + '').split('?')[0];
        var list = search.replace('?', '').split('&');
        var hasIn = false;
        for (var i = 0; i < list.length; i++) {
            var listI = list[i];
            if (listI.split('=')[0].toLowerCase() == paramName.toLowerCase()) { //指定参数
                q = q + (i == 0 ? '?' : '&');
                hasIn = true;
                if (listI.indexOf('=') == -1) { //形式:"参数"
                    q = q + listI + '=' + paramValue;
                } else if (!listI.split('=')[1].length) { //形式："参数="
                    q = q + listI + paramValue;
                } else { //形式:"参数=值"
                    q = q + paramName + '=' + paramValue;
                }
            } else { //其它参数
                q = q + (i == 0 ? '?' : '&');
                q = q + listI;
            }
        }
        if (!hasIn && forceAdding) { //不存在,但必须要添加时
            q = q + '&' + paramName + '=' + paramValue;
        }
        return q;
    }
}

var validatePatterns = {
    "required": [/^[\S+\s*\S+]+$/ig, "不能为空！"],
    "integer": [/^(0|[1-9][0-9]*)$/, "必须为整数！"],
    'password': [/(?!^(\d+|[a-zA-Z]+|[~!@#$%^&*?]+)$)^[\w`~!@#$%^&*\(\)\+\.\?\,\|<>\/\-=\{\[\}\];\'":\\?]{8,16}$/, '[密码]必须包含字母、数字、符号中至少2种，且长度为8-16个，不包括空格'],
    'user': [/^[a-zA-Z][a-zA-Z0-9_]{4,15}$/, '帐号是否合法(字母开头，允许5-16字节，允许字母数字下划线)'],
    "numeric": [/^\d+(\.\d+)?$/, "不是合法的数字！"],
    "currency": [/^\d+\.\d{1,2}$/, "不是合法的货币数字！"],
    "email": [/^\w+@\w+(\.\w+)*$/, "不合法的email输入！"],
    /*"phone":        [/^((0\d{2,3}-\d{7,8})|(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8})$/, "电话不合法！"],*/
    "phone": [/^((0\d{2,3}-\d{7,8})|(0\d{2,3}-\d{7,8}-\d{3,4})|(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8})$/, "电话不合法！"],
    "mustChecked": [/0+/g, "checkbox不能为空！"],
    "mustSelected": [/0+/g, "select不能为空！"],
    "ipAddress": [/^([1-9]|[1-9]\d|1\d{2}|2[0-1]\d|22[0-3])(\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])){3}$/, "不是有效的IP地址！"],
    "netport": [/^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$/, "不合法的端口！"],
    "mac": [/^[0-9,a-f,A-F]{2}[-][0-9,a-f,A-F]{2}[-][0-9,a-f,A-F]{2}[-][0-9,a-f,A-F]{2}[-][0-9,a-f,A-F]{2}[-][0-9,a-f,A-F]{2}$/, "不合法的mac地址！"],
    "IM": [/^[0-9]{15}$/, "不合法的电围地址！"],
    "year": [/^(\d{4})$/, "年份不合法！"],
    "mouth": [/^(\d{4})-(0\d{1}|1[0-2])$/, "月份不合法！"],
    "date": [/^{\d}{4}\-{\d}{2}\-{\d}{2}$/, "日期不合法！"],
    "timeHour": [/^(0\d{1}|1\d{1}|2[0-3])$/, "小时不合法！"], //HH
    "timeMinute": [/^(0\d{1}|1\d{1}|2[0-3]):([0-5]\d{1})$/, "分钟不合法！"], //HH:mm
    "timeSeconds": [/^(0\d{1}|1\d{1}|2[0-3]):[0-5]\d{1}:([0-5]\d{1})$/, "时间不合法！"], //HH:mm:ss
    "chineseOnly": [/[^\u4E00-\u9FA5]/g, "输入不合法！请只输入中文！"],
    // "mobilePhone":  [/^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/, "手机号不合法！"],
    "mobilePhone": [/^(0|86|17951)?(1[3-9][0-9])[0-9]{8}$/, "手机号不合法！"],
    //"unicomPhone":  [/^13[0-4]{1}[\d]{8}$/, "不合法！"],
    //"telecomPhone": [/^(\d{7,8})|(\d{3,4}\-\d{7,8})$/, "不合法！"],
    "specials": [/^[^`~!@#$%^&*()+=|\\\][\]\{\}:;'\,.<>?]{1}[^`~!@$%^&+=\\\][\{\}:;'\,<>?]{0,}$/, "不能输入特殊字符！"],
    "pattern": [null, "数据不合法！请确认"],
    "carCode": [/^([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[a-zA-Z](([DF]((?![IO])[a-zA-Z0-9](?![IO]))[0-9]{4})|([0-9]{5}[DF]))|[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1})$/, "车牌号格式不正确"],
    "idCard": [/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/, "身份证号格式不正确"],
    'postcode': [/^\d{6}$/, "邮编格式不正确"],

    'longitude': [/^-?((180(\.0{0,6})?)|((\d{1,2}|1[0-7]\d)(\.\d{0,6})?))$/, "不是有效的经度！"],
    'latitude': [/^-?((90(\.0{0,6})?)|((\d|[1-8]\d)(\.\d{0,6})?))$/, "不是有效的纬度！"],
    'digitOrLetter': [/^[A-Za-z0-9]*$/, "格式不正确(只支持数字或字母)"],
    "passport": [/^(([PDGES]\d{8})|([PSD]E\d{7}))$/, "护照格式不正确"],
    "hk-passport": [/^[a-zA-Z0-9]{5,21}$/, "港澳通行证格式不正确"],
    "driving": [/^[a-zA-Z0-9]{3,21}$/, "驾照格式不正确"],
    'zh_CN': [/[\uFF00-\uFFFF]/, '中文'],
    'xml文件': [/^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$/, '中文'],
    'qq': [/[1-9][0-9]{4,}/, '腾讯QQ号从10000开始']
};
// 身份证正则
// 电话正则
const idcard_pattern = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
const phone_pattern = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/;
'有两位小数的正实数' = /^[0-9]+(.[0-9]{2})?$/
'有1~3位小数的正实数' = /^[0-9]+(.[0-9]{1,3})?$/
'非零的正整数' = /^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$/
'非零的负整数' = /^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$/
'非负整数' = /^\d+$ 或 ^[1-9]\d*|0$/
'非正整数' = /^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$/
'非负浮点数' = /^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$/
'非正浮点数' = /^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$/
'正浮点数' = /^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$/
'负浮点数' = /^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/
'浮点数' = /^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$/
'全角符号' = /[\uFF00-\uFFFF]/
'半角符号' = /[\u0000-\u00FF]/
'中国邮政编码' = /[1-9]\d{5}(?!\d)/
'子网掩码' = /((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))/
'是否IP-v6地址' = /(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/
'是否IP-v4地址' = /\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b/(提取IP地址时有用)
'yyyy-mm-dd“ 格式的日期校验，已考虑平闰年' = /^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$/
// 爬虫相关
'抽取注释' = /<!--(.*?)-->/
'查找CSS属性' = /^\\s*[a-zA-Z\\-]+\\s*[:]{1}\\s[a-zA-Z0-9\\s.#]+[;]{1}/
'提取页面超链接' = /(<a\\s*(?!.*\\brel=)[^>]*)(href="https?:\\/\\/)((?!(?:(?:www\\.)?'.implode('|(?:www\\.)?', $follow_list).'))[^" rel="external nofollow" ]+)"((?!.*\\brel=)[^>]*)(?:[^>]*)>/
'提取网页图片' = /\\< *[img][^\\\\>]*[src] *= *[\\"\\']{0,1}([^\\"\\'\\ >]*)/
'提取网页颜色代码' = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/

/**
 * 页面数据导出下载(此方式支持参数长度大的方式,支持get,post方式)
 * @param {str} url: 导出服务
 * @param {str} iframeId： iframeid
 * @param {obj} params： 查询参数
 */
function bigDataToDownload (url, iframeId, params) {
    $("#" + iframeId).remove();
    $("body").append('<iframe class="hide" src="about:blank" id="' + iframeId + '" frameborder="0" ></iframe>');
    var dateId = new Date().getTime();
    var html = '<form action="' + url + '" method="post" target="_self" id="' + dateId + '">';
    for (param in params) {
        html = html + "<input id='" + param + "' name='" + param + "' type='hidden' value='" + params[param] + "'/>";
    }
    html = html + '</form>';
    document.getElementById(iframeId).contentWindow.document.write(html);
    document.getElementById(iframeId).contentWindow.document.getElementById(dateId).submit();
}
// 通过a标签导出
function exportFileUtil (options) {
    var aEle = document.createElement("a"); // 创建a标签
    aEle.href = options.url; // content为后台返回的下载地址
    aEle.download = ""; // 设置下载文件的文件名
    aEle.click(); // 设置点击事件
    // $(aEle).remove();
}
//日期比较时间大小
function compareTime (firstTime, secondTime) {
    var d1 = new Date((firstTime + '').replace(/\-/g, "\/"));
    var d2 = new Date((secondTime + '').replace(/\-/g, "\/"));
    if (firstTime != "" && secondTime != "" && d1 >= d2) {
        //firstTime > secondTime
        return true;
    } else {
        return false;
    }
}
//两个时间相差天数 兼容firefox chrome
function datedifference (sDate1, sDate2) { //sDate1和sDate2是2006-12-18格式
    var dateSpan,
        tempDate,
        iDays;
    sDate1 = Date.parse(sDate1);
    sDate2 = Date.parse(sDate2);
    dateSpan = sDate2 - sDate1;
    dateSpan = Math.abs(dateSpan);
    iDays = Math.ceil(dateSpan / (24 * 3600 * 1000));
}
// 获取当天凌晨的时间
function getStartTime () {
    var today = new Date();
    today.setHours(0);
    today.setMinutes(0);
    today.setSeconds(0);
    today.setMilliseconds(0);
    return today;
}

function getDescByMonth (endDay) {
    var rest = [];
    for (var i = 1; i <= endDay; i++) {
        rest.push(i + "号");
    }
    return rest;
}

function getDescByDay () {
    var rest = [];
    for (var i = 0; i <= 23; i++) {
        rest.push(i + "时");
    }
    return rest;
}

function getDescByWeek () {
    var rest = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
    return rest;
}

function getDescByYear () {
    var rest = [];
    for (var i = 1; i <= 12; i++) {
        rest.push(i + "月");
    }
    return rest;
}
/**
 * getDateTime根据描述获取时间
 * date = UI.util.getDateTime('today', 'yyyy-MM-dd HH:mm:ss');
 */
function getDateTime (obj, format) {
    var defaultDateFromat = "yyyy-MM-dd",
        result = {},
        desc = [];
    var dateTime = new Array(),
        bt = new Date(),
        et = new Date(),
        _weekday = bt.getDay(),
        _monthday = bt.getDate(),
        y = bt.getFullYear(),
        m = bt.getMonth() + 1,
        endDay = new Date(y, m, 0).getDate();
    if (_weekday == 0) {
        _weekday = 7;
    }
    desc = getDescByDay();
    if (obj == 'yesterday') {
        bt.setDate(bt.getDate() - 1);
        et.setDate(et.getDate() - 1);
        desc = getDescByDay();
    } else if (obj == "thisWeek") {
        bt.setDate(bt.getDate() - (_weekday - 1));
        desc = getDescByWeek();
    } else if (obj == "thisFullWeek") {
        bt.setDate(bt.getDate() - (_weekday - 1));
        et.setDate(et.getDate() + (7 - _weekday));
        desc = getDescByWeek();
    } else if (obj == "lastWeek") {
        bt.setDate(bt.getDate() - 7 + (1 - _weekday));
        et.setDate(et.getDate() - _weekday);
        desc = getDescByWeek();
    } else if (obj == "thisMonth") {
        bt.setDate(bt.getDate() + (1 - _monthday));
        desc = getDescByMonth(endDay);
    } else if (obj == "nearWeek") { //最近一周
        bt.setDate(bt.getDate() - 6);
        et.setDate(et.getDate());
    } else if (obj == "nearMonth") { //最近30天
        bt.setDate(bt.getDate() - 29);
        et.setDate(et.getDate());
    } else if (obj == "2nearMonth") { //最近60天
        bt.setDate(bt.getDate() - 59);
        et.setDate(et.getDate());
    } else if (obj == "thisFullMonth") {
        bt.setDate(bt.getDate() + (1 - _monthday));
        et.setDate(endDay);
        desc = getDescByMonth(endDay);
    } else if (obj == "lastMonth") {
        endDay = new Date(y, m - 1, 0).getDate();
        bt.setMonth(bt.getMonth() - 1);
        et.setMonth(et.getMonth());
        var _dayNum = (et - bt) / (24 * 60 * 60 * 1000);
        bt.setDate(bt.getDate() + (1 - _monthday));
        et.setDate(et.getDate() - _monthday);
        desc = getDescByMonth(endDay);
    } else if (obj == "thisYear") {
        bt = new Date(et.getFullYear() + "-01-01");
        desc = getDescByYear();
    } else if (obj == 'nextMonth') { // 下个月
        var nYear = y; // 下一年
        var nMonth = parseInt(m) + 1; // 下一个月
        if (nMonth == 13) {
            nYear = parseInt(y) + 1;
            nMonth = 1;
        }
        var today = bt.getDate(); // 今日
        var nMonthDays = new Date(nYear, nMonth, 0).getDate(); // 下个月的天数
        if (today > nMonthDays) {
            today = nMonthDays;
        }
        if (nMonth < 10) {
            nMonth = '0' + nMonth;
        }
        bt = et = new Date(nYear + '-' + nMonth + '-' + today);
    } else if (obj == 'nextThreeMonth') { // 三个月后
        bt = et = new Date(y, m + 2, bt.getDate());
    } else if (obj == 'nextSixMonth') { // 六个月后
        bt = et = new Date(y, m + 5, bt.getDate());
    } else if (obj == 'beforeThreeMonth') { // 3个月前
        bt = et = new Date(y, m - 4, bt.getDate());
    }
    if (!format) {
        format = defaultDateFromat;
    }
    var bT = bt.format(format);
    var eT = et.format(format);
    if (format == "yyyy-MM-dd HH:mm:ss") {
        bT = bt.format(defaultDateFromat + ' 00:00:00');
        eT = et.format(defaultDateFromat + ' 23:59:59');
    }

    function getDescByMonth (endDay) {
        var rest = [];
        for (var i = 1; i <= endDay; i++) {
            rest.push(i + "号");
        }
        return rest;
    }

    function getDescByDay () {
        var rest = [];
        for (var i = 0; i <= 23; i++) {
            rest.push(i + "时");
        }
        return rest;
    }

    function getDescByWeek () {
        var rest = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
        return rest;
    }

    function getDescByYear () {
        var rest = [];
        for (var i = 1; i <= 12; i++) {
            rest.push(i + "月");
        }
        return rest;
    }
    result = {
        bT: bT,
        eT: eT,
        desc: desc
    }
    UI.util.debug(result);
    return result;
}
/**
 * 格式化数字  如：1435454   格式化后：1,435,454
 * */
function renderNumber (num) {
    var ret = "";
    ret += num;
    if (num != null && num != '') {
        ret = ret.split("").reverse().join("").replace(/(\d{3})(?=[^$])/g, "$1,").split("").reverse().join("");
    }
    return ret;
}
//isSpace:true 表示所选开始时间大于前space天
function timeLinkage (options) {
    var defaults = {
        begin: '',
        end: '',
        space: 6,
        format: 'yyyy-MM-dd'
    }
    var options = $.extend(true, defaults, options);
    options.begin = options.begin.replace(/\-/g, "/");
    options.end = options.end.replace(/\-/g, "/");
    var begin = new Date(options.begin);
    var end = new Date(options.end);
    var spaceDate = new Date(end.getTime() - (options.space) * 24 * 3600 * 1000);
    var isSpace = begin.getTime() > spaceDate.getTime();
    return isSpace
}

/**
 * 将null，undefined类型 转换为空字符串
 */
this.strToString = function (string) {
    if (string == null || string == "null" || string == 'NULL' || string == undefined
        || str == 'undefined' || str == 'UNDEFINED') {
        return "";
    }

    return string;
}

/**
	 * 对象深度克隆
	 * @param obj 克隆对象
	 */
function clone (obj) {
    var o, obj;
    if (obj.constructor == Object) {
        o = new obj.constructor();
    } else {
        o = new obj.constructor(obj.valueOf());
    }
    for (var key in obj) {
        if (o[key] != obj[key]) {
            if (typeof (obj[key]) == 'object') {
                o[key] = this.clone(obj[key]);
            } else {
                o[key] = obj[key];
            }
        }
    }
    o.toString = obj.toString;
    o.valueOf = obj.valueOf;
    return o;
};


//空字符串或者null转变为“未知”
function renderNullToNotKnow (str) {
    if (str == null || str == "" || typeof (str) == "undefined" || str == "PLATE") {
        return "未知";
    } else {
        return str;
    }
}

// 判断是否为空对象
function isEmpty (obj) {
    for (let key in obj) {
        return false;
    }
    return true;
}

function uuid (len, radix) {
    var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
    var uuid = [], i;
    radix = radix || chars.length;

    if (len) {
        // Compact form
        for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
    } else {
        // rfc4122, version 4 form
        var r;

        // rfc4122 requires these characters
        uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
        uuid[14] = '4';

        // Fill in random data.  At i==19 set the high bits of clock sequence as
        // per rfc4122, sec. 4.1.5
        for (i = 0; i < 36; i++) {
            if (!uuid[i]) {
                r = 0 | Math.random() * 16;
                uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
            }
        }
    }

    return uuid.join('');
}





// 递归获取目录下的所有文件
function readFileList (dir, fileList) {
    const files = fs.readdirSync(dir);
    files.forEach(filename => {
        let filePath = path.resolve(dir, filename);
        const stat = fs.statSync(filePath);
        if (stat.isDirectory()) {
            readFileList(filePath, fileList);
        } else {
            const file = fs.readFileSync(path.resolve(dir, filename), 'utf-8');
            const start = file.indexOf(START_SYMBOL) + START_SYMBOL.length;
            const end = file.indexOf(END_SYMBOL);
            let queryPath = file.slice(start, end).slice(1);
            let obj = {};
            obj.path = dir;
            obj.filename = filename;
            obj.queryPath = queryPath;
            fileList.push(obj);
        }
    });
}

// 获取目录下的所有文件
function getFileList (dir) {
    let fileList = [];
    readFileList(dir, fileList);
    return fileList;
}

// 清除目录，包括目录本身
function cleanDir (dir) {
    let files = [];
    if (fs.existsSync(dir)) {
        files = fs.readdirSync(dir);
        files.forEach(function (filename, index) {
            const curPath = path.resolve(dir, filename);
            if (fs.statSync(curPath).isDirectory()) { // recurse
                cleanDir(curPath);
            } else { // delete file
                fs.unlinkSync(curPath);
            }
        });
        fs.rmdirSync(dir);
    }
}

/*
 * 获取今日时间 时间格式转化 传时间对象 得到 2017-7-16 12:12:12 ,传空默认返回当前;
 * @param {String} time : 时间戳
 * @param {boor} boor : 是否要时分秒 默认不要
 * @return {str} currentdate : 格式为 2017-7-16 12:12:12 的字符串
 * @author  lzh
 */
function trans (time, boor) {
    var time = time || new Date();
    var seperator1 = "-";
    var seperator2 = ":";
    var month = time.getMonth() + 1;
    var strDate = time.getDate();
    if (month >= 1 && month <= 9) {
        month = "0" + month;
    }
    if (strDate >= 0 && strDate <= 9) {
        strDate = "0" + strDate;
    }
    if (!boor) {
        var currentdate = time.getFullYear() + seperator1 + month + seperator1 + strDate
    } else {
        var currentdate = time.getFullYear() + seperator1 + month + seperator1 + strDate
            + " " + time.getHours() + seperator2 + time.getMinutes()
            + seperator2 + time.getSeconds();
    }
    return currentdate;
}
// 判断是否为ie浏览器
function browserIsIE () {
    if (!!window.ActiveXObject || 'ActiveXObject' in window) {
        return true;
    } else {
        return false;
    }
}


//正则验证
var patterns = {};
patterns.phone = /^1[3|4|5|7|8]\d{9}$/;
patterns.wifi = /[A-F\d]{2}:[A-F\d]{2}:[A-F\d]{2}:[A-F\d]{2}:[A-F\d]{2}:[A-F\d]{2}/;
patterns.car = /^[\u4e00-\u9fa5]{1}[A-Z]{1}[A-Z_0-9]{5}$/;
patterns.idcard = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
patterns.door = /^[\S+\s*\S+]+$/ig;

function matchPatterns (value, type) {
    var pattern = patterns[type];
    return value.toUpperCase().match(pattern);
}


// 获取两个时间节点之间的所有日期
function getRangeDay (beginDate, endDate, formats) {
    var ranges = [];
    var end = newDay(endDate);
    var date = newDay(beginDate);
    if (!formats) {
        formats = 'yyyyMMdd';
    }
    while (end >= date) {
        ranges.push(date.format(formats));
        date.setDate(date.getDate() + 1);
    }
    return ranges.join(",");
}




function isString (obj) {
    return Object.prototype.toString.call(obj) === '[object String]';
}

function isObject (obj) {
    return Object.prototype.toString.call(obj) === '[object Object]';
}
function isUndefined (obj) {
    return obj === void 0;
}

function isFunction (functionToCheck) {
    var getType = {};
    return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
};




//getDate('2017-10-10')字符串转标准日期Tue Oct 10 2017 00:00:00 GMT+0800 (中国标准时间)，strDate要转为日期格式的字符串
function getDate (strDate) {
    var date = eval('new Date(' + strDate.replace(/\d+(?=-[^-]+$)/,
        function (a) { return parseInt(a, 10) - 1; }).match(/\d+/g) + ')');
    return date;
}


// 数组排序使用
function sortByKey (array, key) {
    return array.sort(function (a, b) {
        var x = a[key];
        var y = b[key];
        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
    });
}
//用于生成随机字符串
function S4 () {
    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}
function guid () {
    return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
}